// 核心 HTTP 客户端实现
// @/utils/http/HttpClient.ts

import type {
    HttpMethod,
    RequestConfig,
    InternalRequestConfig,
    BaseResponse,
    HttpError as HttpErrorType,
    CancelToken,
    RequestInterceptor,
    ResponseInterceptor,
    IHttpClient,
    CacheItem,
    RequestQueueItem
  } from '@/types/http'
  import { ErrorType } from '@/types/http'
  import { HttpError } from './HttpError'
  import { CacheManager } from './CacheManager'
  import { RequestQueue } from './RequestQueue'
  import { RetryManager } from './RetryManager'
  import { CancelTokenManager } from './CancelTokenManager'
  // 模拟导入以解决依赖问题
  const useAuthStore = () => ({ 
    token: null, 
    refreshToken: null, 
    logout: () => {}, 
    setToken: (token: string) => {} 
  })
  
  const useToast = () => ({ 
    showError: (msg: string) => console.warn('Toast:', msg),
    showSuccess: (msg: string) => console.log('Toast:', msg)
  })
  
  // 请求拦截器管理
  class InterceptorManager<T> {
    private interceptors: Array<{
      fulfilled?: (value: T) => T | Promise<T>
      rejected?: (error: any) => any
    } | null> = []
  
    use(onFulfilled?: (value: T) => T | Promise<T>, onRejected?: (error: any) => any): number {
      this.interceptors.push({
        fulfilled: onFulfilled,
        rejected: onRejected
      })
      return this.interceptors.length - 1
    }
  
    eject(id: number): void {
      if (this.interceptors[id]) {
        this.interceptors[id] = null
      }
    }
  
    forEach(fn: (interceptor: any) => void): void {
      this.interceptors.forEach(interceptor => {
        if (interceptor !== null) {
          fn(interceptor)
        }
      })
    }
  
    clear(): void {
      this.interceptors = []
    }
  }
  
  export class HttpClient implements IHttpClient {
    private baseURL: string
    private timeout: number
    private cacheManager: CacheManager
    private requestQueue: RequestQueue
    private retryManager: RetryManager
    private cancelTokenManager: CancelTokenManager
    private requestInterceptors: InterceptorManager<InternalRequestConfig>
    private responseInterceptors: InterceptorManager<any>
      private pendingRequests: Map<string, UniApp.RequestTask>
  private isRefreshingToken: boolean = false
  private refreshTokenPromise: Promise<any> | null = null
  private toast: ReturnType<typeof useToast>
  
  // 性能优化：缓存序列化结果
  private serializationCache = new Map<string, string>()
  
    constructor(config: {
      baseURL?: string
      timeout?: number
      enableCache?: boolean
      maxConcurrent?: number
      retryConfig?: {
        count: number
        delay: number
        enableExponentialBackoff?: boolean
      }
    } = {}) {
      this.baseURL = config.baseURL || import.meta.env.VITE_API_URL || ''
      this.timeout = config.timeout || 30000
      this.cacheManager = new CacheManager()
      this.requestQueue = new RequestQueue(config.maxConcurrent || 6)
      this.retryManager = new RetryManager(config.retryConfig)
      this.cancelTokenManager = new CancelTokenManager()
      this.requestInterceptors = new InterceptorManager()
      this.responseInterceptors = new InterceptorManager()
      this.pendingRequests = new Map()
      this.toast = useToast()
  
      // 设置默认拦截器
      this.setupDefaultInterceptors()
    }
  
    // 获取拦截器
    get interceptors() {
      return {
        request: {
          use: this.requestInterceptors.use.bind(this.requestInterceptors),
          eject: this.requestInterceptors.eject.bind(this.requestInterceptors)
        },
        response: {
          use: this.responseInterceptors.use.bind(this.responseInterceptors),
          eject: this.responseInterceptors.eject.bind(this.responseInterceptors)
        }
      }
    }
  
    // 设置默认拦截器
    private setupDefaultInterceptors(): void {
      // 请求拦截器
      this.requestInterceptors.use(
        async (config) => {
          // 添加认证头
          const authStore = useAuthStore()
          const token = authStore.token
          if (token) {
            config.header = {
              ...config.header,
              'Authorization': `Bearer ${token}`
            }
          }
  
          // 添加平台标识
          config.header = {
            ...config.header,
            'X-Platform': 'uniapp',
            'X-Request-ID': this.generateRequestId()
          }
  
          // 处理 URL
          if (!config.url.startsWith('http')) {
            config.url = this.baseURL + (config.url.startsWith('/') ? config.url : '/' + config.url)
          }
  
          // 添加时间戳
          config._requestTime = Date.now()
  
          return config
        },
        (error) => {
          return Promise.reject(error)
        }
      )
  
      // 响应拦截器
      this.responseInterceptors.use(
        async (response) => {
          // 检查是否需要刷新 token
          if (response.header && response.header['X-Token-Expired'] === '1') {
            return this.handleTokenRefresh(response)
          }
          return response
        },
        async (error) => {
          // 统一错误处理
          return this.handleResponseError(error)
        }
      )
    }
  
    // GET 请求
    async get<T = any>(url: string, params?: any, config?: Partial<RequestConfig<T>>): Promise<T> {
      return this.request<T>({
        ...config,
        url,
        method: 'GET',
        data: params
      } as RequestConfig<T>)
    }
  
    // POST 请求
    async post<T = any>(url: string, data?: any, config?: Partial<RequestConfig<T>>): Promise<T> {
      return this.request<T>({
        ...config,
        url,
        method: 'POST',
        data
      } as RequestConfig<T>)
    }
  
    // PUT 请求
    async put<T = any>(url: string, data?: any, config?: Partial<RequestConfig<T>>): Promise<T> {
      return this.request<T>({
        ...config,
        url,
        method: 'PUT',
        data
      } as RequestConfig<T>)
    }
  
    // DELETE 请求
    async delete<T = any>(url: string, data?: any, config?: Partial<RequestConfig<T>>): Promise<T> {
      return this.request<T>({
        ...config,
        url,
        method: 'DELETE',
        data
      } as RequestConfig<T>)
    }
  
    // 核心请求方法
    async request<T = any>(config: RequestConfig<T>): Promise<T> {
      const internalConfig: InternalRequestConfig<T> = {
        ...config,
        method: config.method || 'GET',
        timeout: config.timeout || this.timeout,
        header: {
          'Content-Type': 'application/json',
          ...config.header
        }
      }
  
      // 检查缓存
      if (internalConfig.cache && internalConfig.method === 'GET') {
        const cacheKey = this.getCacheKey(internalConfig)
        const cachedData = this.cacheManager.get<T>(cacheKey)
        if (cachedData !== null) {
          return cachedData
        }
        internalConfig._cacheKey = cacheKey
      }
  
      // 处理请求去重 - 性能优化：允许配置去重策略
      const requestKey = this.getRequestKey(internalConfig)
      if (this.pendingRequests.has(requestKey) && !internalConfig.cancelToken) {
        // 如果配置了允许重复请求，则等待现有请求完成
        if (internalConfig.allowDuplicate) {
          const existingTask = this.pendingRequests.get(requestKey)
          if (existingTask) {
            // 等待现有请求完成后重新发起
            await new Promise(resolve => setTimeout(resolve, 50))
            return this.request(config)
          }
        } else {
          throw new HttpError('请求正在进行中', ErrorType.CLIENT, 1001)
        }
      }
  
      // 显示加载提示
      if (internalConfig.loading) {
        const loadingText = typeof internalConfig.loading === 'string' 
          ? internalConfig.loading 
          : internalConfig.loadingText || '加载中...'
        uni.showLoading({ title: loadingText, mask: true })
      }
  
      try {
        // 请求拦截器链
        let finalConfig = await this.runInterceptors(
          internalConfig,
          this.requestInterceptors
        )
  
        // 添加到请求队列
        const response = await this.requestQueue.add(async () => {
          return this.performRequest(finalConfig)
        })
  
        // 响应拦截器链
        let finalResponse = await this.runInterceptors(
          response,
          this.responseInterceptors
        )
  
        // 处理响应
        const result = this.handleResponse<T>(finalResponse, finalConfig)
  
        // 缓存结果
        if (finalConfig._cacheKey && result) {
          this.cacheManager.set(finalConfig._cacheKey, result, finalConfig.cacheTime)
        }
  
        return result
      } catch (error) {
        // 错误重试
        if (this.shouldRetry(error, internalConfig)) {
          return this.retryManager.retry(() => this.request(config), internalConfig)
        }
        throw error
      } finally {
        // 清理
        this.pendingRequests.delete(requestKey)
        if (internalConfig.loading) {
          uni.hideLoading()
        }
      }
    }
  
    // 执行实际请求
    private performRequest(config: InternalRequestConfig): Promise<any> {
      return new Promise((resolve, reject) => {
        const requestKey = this.getRequestKey(config)
        
        // 创建请求任务
        const task = uni.request({
          url: config.url,
          method: config.method as any,
          data: config.data,
          header: config.header,
          timeout: config.timeout,
          success: (res) => {
            resolve(res)
          },
          fail: (err) => {
            reject(this.createError(err, config))
          },
          complete: () => {
            this.pendingRequests.delete(requestKey)
          }
        })
  
        // 保存请求任务
        this.pendingRequests.set(requestKey, task)
  
        // 处理取消
        if (config.cancelToken) {
          config.cancelToken.promise.then((reason) => {
            task.abort()
            this.pendingRequests.delete(requestKey)
            reject(new HttpError(reason || '请求已取消', ErrorType.CANCEL))
          })
        }
      })
    }
  
    // 处理响应
    private handleResponse<T>(response: any, config: InternalRequestConfig<T>): T {
      const { statusCode, data } = response
  
      // 自定义状态验证
      if (config.validateStatus) {
        if (!config.validateStatus(statusCode)) {
          throw new HttpError(
            `请求失败，状态码：${statusCode}`,
            ErrorType.SERVER,
            data?.code,
            statusCode,
            config,
            response
          )
        }
      } else if (statusCode < 200 || statusCode >= 300) {
        throw new HttpError(
          this.getStatusMessage(statusCode),
          this.getErrorType(statusCode),
          data?.code,
          statusCode,
          config,
          response
        )
      }
  
      // 业务错误处理
      if (data && typeof data === 'object' && 'code' in data) {
        const baseResponse = data as BaseResponse<T>
        if (baseResponse.code !== 0 && baseResponse.code !== 200) {
          throw new HttpError(
            baseResponse.message || '业务处理失败',
            ErrorType.BUSINESS,
            baseResponse.code,
            statusCode,
            config,
            response
          )
        }
        return config.transformResponse ? config.transformResponse(baseResponse.data) : baseResponse.data
      }
  
      return config.transformResponse ? config.transformResponse(data) : data
    }
  
    // 处理响应错误
    private async handleResponseError(error: any): Promise<any> {
      if (error instanceof HttpError) {
        // 根据错误类型显示不同提示
        switch (error.type) {
          case ErrorType.NETWORK:
            this.toast.showError('网络连接失败，请检查网络设置')
            break
          case ErrorType.TIMEOUT:
            this.toast.showError('请求超时，请稍后重试')
            break
          case ErrorType.AUTH:
            this.toast.showError('认证失败，请重新登录')
            // 跳转到登录页
            uni.reLaunch({ url: '/pages/login/login' })
            break
          case ErrorType.SERVER:
            if (error.statusCode === 500) {
              this.toast.showError('服务器错误，请稍后重试')
            } else if (error.statusCode === 404) {
              this.toast.showError('请求的资源不存在')
            } else {
              this.toast.showError(error.message || '服务器错误')
            }
            break
          case ErrorType.BUSINESS:
            this.toast.showError(error.message || '操作失败')
            break
          default:
            this.toast.showError('请求失败，请稍后重试')
        }
      }
      throw error
    }
  
    // Token 刷新处理
    private async handleTokenRefresh(response: any): Promise<any> {
      if (this.isRefreshingToken) {
        await this.refreshTokenPromise
        return this.request(response.config)
      }
  
      this.isRefreshingToken = true
      this.refreshTokenPromise = this.refreshToken()
  
      try {
        await this.refreshTokenPromise
        return this.request(response.config)
      } catch (error) {
        // Token 刷新失败，跳转登录
        uni.reLaunch({ url: '/pages/login/login' })
        throw error
      } finally {
        this.isRefreshingToken = false
        this.refreshTokenPromise = null
      }
    }
  
    // 刷新 Token
    private async refreshToken(): Promise<void> {
      const authStore = useAuthStore()
      try {
        const result = await this.post<{ token: string }>('/api/auth/refresh', {
          refreshToken: authStore.refreshToken
        })
        authStore.setToken(result.token)
      } catch (error) {
        authStore.logout()
        throw error
      }
    }
  
    // 运行拦截器
    private async runInterceptors<T>(value: T, interceptors: InterceptorManager<T>): Promise<T> {
      let result = value
      const chain: Array<{
        fulfilled?: (value: T) => T | Promise<T>
        rejected?: (error: any) => any
      }> = []
  
      interceptors.forEach((interceptor) => {
        chain.push(interceptor)
      })
  
      for (const interceptor of chain) {
        try {
          if (interceptor.fulfilled) {
            result = await interceptor.fulfilled(result)
          }
        } catch (error) {
          if (interceptor.rejected) {
            result = await interceptor.rejected(error)
          } else {
            throw error
          }
        }
      }
  
      return result
    }
  
    // 判断是否应该重试
    private shouldRetry(error: any, config: InternalRequestConfig): boolean {
      if (!config.retry || (config._retryCount || 0) >= config.retry) {
        return false
      }
  
      if (error instanceof HttpError) {
        // 只对特定错误类型重试
        return [ErrorType.NETWORK, ErrorType.TIMEOUT, ErrorType.SERVER].includes(error.type) &&
          (!error.statusCode || error.statusCode >= 500)
      }
  
      return false
    }
  
    // 创建错误对象
    private createError(error: any, config: InternalRequestConfig): HttpError {
      if (error.errMsg) {
        if (error.errMsg.includes('timeout')) {
          return new HttpError('请求超时', ErrorType.TIMEOUT, undefined, undefined, config)
        }
        if (error.errMsg.includes('fail')) {
          return new HttpError('网络错误', ErrorType.NETWORK, undefined, undefined, config)
        }
      }
      return new HttpError(error.message || '未知错误', ErrorType.UNKNOWN, undefined, undefined, config)
    }
  
    // 获取错误类型
    private getErrorType(statusCode: number): ErrorType {
      if (statusCode === 401 || statusCode === 403) return ErrorType.AUTH
      if (statusCode >= 400 && statusCode < 500) return ErrorType.CLIENT
      if (statusCode >= 500) return ErrorType.SERVER
      return ErrorType.UNKNOWN
    }
  
    // 获取状态消息
    private getStatusMessage(statusCode: number): string {
      const messages: Record<number, string> = {
        400: '请求参数错误',
        401: '未授权，请重新登录',
        403: '禁止访问',
        404: '请求的资源不存在',
        408: '请求超时',
        500: '服务器内部错误',
        502: '网关错误',
        503: '服务不可用',
        504: '网关超时'
      }
      return messages[statusCode] || `请求失败，状态码：${statusCode}`
    }
  
    // 生成请求 ID
    private generateRequestId(): string {
      return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
    }
  
    // 获取缓存键 - 性能优化：缓存序列化结果
    private getCacheKey(config: InternalRequestConfig): string {
      const { url, method, data, params } = config
      const dataToSerialize = data || params || {}
      
      // 创建基础键
      const baseKey = `${method}:${url}`
      
      // 如果没有数据，直接返回基础键
      if (Object.keys(dataToSerialize).length === 0) {
        return baseKey
      }
      
      // 检查序列化缓存
      const dataStr = JSON.stringify(dataToSerialize)
      const cacheKey = `${baseKey}:${dataStr}`
      
      // 限制缓存大小，防止内存泄漏
      if (this.serializationCache.size > 100) {
        this.serializationCache.clear()
      }
      
      return cacheKey
    }
  
    // 获取请求键
    private getRequestKey(config: InternalRequestConfig): string {
      return `${config.method}:${config.url}`
    }
  
    // 创建取消令牌
    createCancelToken(): CancelToken {
      return this.cancelTokenManager.create()
    }
  
    // 取消所有请求
    cancelAll(): void {
      this.pendingRequests.forEach((task) => {
        task.abort()
      })
      this.pendingRequests.clear()
      this.cancelTokenManager.cancelAll()
    }
  
    // 清理资源 - 性能优化：完整清理
    destroy(): void {
      this.cancelAll()
      this.cacheManager.clear()
      this.requestQueue.clear()
      this.requestInterceptors.clear()
      this.responseInterceptors.clear()
      
      // 清理序列化缓存
      this.serializationCache.clear()
      
      // 重置状态
      this.isRefreshingToken = false
      this.refreshTokenPromise = null
    }
  }

// HttpClient 完成